<?php

namespace app\devices\service;

use think\admin\Service;
use think\cache\driver\Redis;
use think\facade\Log;

/**
 * Socket
 * Class SocketService
 * @package app\devices\service
 */
class SocketService extends Service
{
    /**
     * 向物理机发起socket请求.
     * @param $args
     * @param int $is_send 1.发送指令 0.存入队列
     * @return bool
     * @throws \Exception
     */
    function sendSocket($args, $is_send=0)
    {
        set_time_limit(0);
        ini_set('memory_limit', -1);

        $type = isset($args['type']) ? $args['type'] : 0;

        if (!$type && !is_array($args)) throw new \Exception('类型参数错误');

        $redis = new Redis();
        $device_id = $args['device_id']??"";
        $now_send = $args['is_send']??0;
        if($device_id && $now_send){
            $is_send = 1;
        }

        if(isset($args['device_id']) && $is_send!=1){
            $redis->handler()->RPUSH("SocketDev", $args['device_id']);
            $redis->handler()->RPUSH('LockSocket'.$args['device_id'], json_encode($args, 256));
            return true;
        }

        $port = 8082;
        $ip = "0.0.0.0";

        // 创建socket
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

        if ($socket <= 0) throw new \Exception('创建socket失败,REASON:' . socket_strerror($socket));

        try {

            // 连接服务器
            $result = socket_connect($socket, $ip, $port);

            if ($result < 0 || is_null($result) || !$result) throw new \Exception('连接失败,REASON:' . socket_strerror($result));

            $in = json_encode($args);

            // 写入文件信息
            if (!socket_write($socket, $in, strlen($in))) throw new \Exception('消息发送失败,REASON:' . socket_strerror($socket));

            // 读取socket返回的数据
            $info = $this->socketRead($socket, 0);

//            if ($type != 3 && $error != 0) throw new \Exception('104服务器异常,REASON:' . $msg);
            // 关闭socket
            socket_close($socket);

            return true;
        } catch (\Exception $ex) {
            // 关闭socket
            @socket_close($socket);

            Log::error("Line:".$ex->getLine().",errorMsg：".$ex->getMessage());
            return false;
        }
    }

    /**
     * 读取socket数据.
     *
     * @author yzm
     *
     * @param $socket
     * @param bool|true $isDividePkg
     * @return array|null|string
     */
    function socketRead($socket, $isDividePkg = true)
    {
        $rst = null;

        $buf = socket_read($socket, 8192);
        if ($isDividePkg) {
            $_buf = @json_decode($buf, true);
            $rst = !empty($_buf) ? [$_buf['error'], $_buf['msg'], @$_buf['content']] : $buf;
        } else {
            $rst = $buf;
        }

        return $rst;
    }

}